<?php
declare (strict_types = 1);
namespace app\user\logic\user;

use app\user\model\user\Account as UserModel;
use app\user\model\user\Token as UserTokenModel;
use think\helper\Str;
use app\admin\logic\system\Config as SystemConfig;

/**
 * @method whereAk(string $ak)
 * @method whereUserId(mixed $id)
 */
class Token extends UserTokenModel
{
    /**
     * 生成token
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param UserModel $user [description]
     * @return bool [type]                               [description]
     */
    protected function createToken(UserModel $user): bool
    {
        $ak = Str::random(16);
        $sk = Str::random(16);

        if ($this->whereAk($ak)->whereSk($sk)->whereUserId($user->id)->find()) {
            return $this->createToken($user);
        }

        return $this->data(['ak' => $ak, 'sk' => $sk, 'user_id' => $user->id])->save();
    }

    /**
     * 获取token
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param UserModel $user [description]
     * @return UserModel
     */
    public function getToken(UserModel $user): UserModel
    {
        $token = $this->where('user_id', $user->id)->findOrEmpty();

        if ($token->isEmpty()) {
            // 创建token
            $this->createToken($user);
        }

        return $this->bindToken($user, $this->ak, $this->sk);

    }

    /**
     * 给用户模型绑定授权
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-11
     *
     * @param UserModel $user [description]
     * @param           $ak
     * @param           $sk
     * @return UserModel [type]                               [description]
     */
    public function bindToken(UserModel $user, $ak, $sk): UserModel
    {
        $device_type      = request()->device_type;
        $is_app           = $device_type == 'ios' || $device_type == 'android';
        $user->auth_scope = $is_app ? 'app' : $device_type;
        $user->auth_token = [
            'ak' => $ak,
            'sk' => $sk,
        ];

        return $user;
    }

    /**
     * 根据token获取用户
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param string $ak [description]
     * @param string $sk [description]
     * @return false|mixed [type]                             [description]
     */
    public function getUserWithToken(string $ak, string $sk)
    {
        $token = $this->where('ak', $ak)->where('sk', $sk)->findOrEmpty();
        if ($token->isEmpty()) {
            return false;
        }

        return $token->user;
    }

    /**
     * 清空所有token
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param UserModel $user [description]
     * @return void [type]                               [description]
     */
    public function clearToken(UserModel $user): void
    {
        $this->where('user_id', $user->id)->delete();
    }

    /**
     * 刷新当前用户的token
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param UserModel $user [description]
     * @return UserModel [type]                               [description]
     */
    public function refreshToken(UserModel $user): UserModel
    {
        // 未查询到直接执行绑定
        $token = $this->whereUserId($user->id)->find();
        if (!$token) {
            $this->createToken($user);
            return $this->bindToken($user, $this->ak, $this->sk);
        }

        $ak = Str::random(16);
        $sk = Str::random(16);

        $uniqueLoginConf = SystemConfig::get('system.login', [], request()->mhm_id);
        $uniqueLogin     = $uniqueLoginConf['unique']??0;

        if ( $uniqueLogin ) {
            $this->withoutGlobalScope(['deviceType'])->whereUserId($user->id)->update(['ak' => $ak, 'sk' => $sk ]);
        } else {
            $token->ak = $ak;
            $token->sk = $sk;
            $token->save();
        }

        return $this->bindToken($user, $ak, $sk);
    }

}
